package ru.alt22.visor.php.ui.swt;

import org.eclipse.core.resources.IProject;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.php.internal.core.phpModel.phpElementData.PHPClassData;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.events.TraverseEvent;

import ru.alt22.visor.php.core.reflection.ReflectionUtils;
import ru.alt22.visor.php.ui.providers.PHPElementContentProvider;
import ru.alt22.visor.php.ui.utils.LayoutUtils;

public class OpenPhpClassDialog extends Dialog {
	private boolean forClasses;
	private PHPClassData[] phpClasses;
	private PHPClassData selectedClass;
	private Text filter;
	private String filterText;
	private PHPElementSelector classes;
	private IProject project = null;

	public OpenPhpClassDialog(Shell parentShell) {
		this(parentShell, true);
	}

	public OpenPhpClassDialog(Shell parentShell, boolean forClasses) {
		super(parentShell);
		setShellStyle(getShellStyle() | SWT.RESIZE);
		this.forClasses = forClasses;
	}

	public void setProject(IProject project) {
		this.project = project;
	}

	public void setFilterText(String text) {
		filterText = text;
	}

	public PHPClassData getSelectedClass() {
		return selectedClass;
	}

	protected Point getInitialSize() {
		return getShell().computeSize(500, 400, true);
	}

	protected Control createDialogArea(Composite parent) {
		Composite composite = (Composite) super.createDialogArea(parent);

		GridLayout layout = new GridLayout();
		composite.setLayout(layout);
		layout.numColumns = 2;
		layout.verticalSpacing = 9;
		
		Label label = new Label(composite, SWT.NULL);
		label.setText("Filter:");
		
		filter = new Text(composite, SWT.BORDER | SWT.SINGLE);
		if (filterText != null) {
			filter.setText(filterText);
		}
		filter.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				handleFilterModify();
			}
		});
		filter.addKeyListener(new KeyListener() {
			public void keyPressed(KeyEvent e) {
				handleFilterKeys(e);
			}
			public void keyReleased(KeyEvent e) {
			}
		});
		filter.addTraverseListener(new TraverseListener() {
			public void keyTraversed(TraverseEvent e) {
				handleFilterKeys(e);
			}
		});
		LayoutUtils.setGridData(filter, GridData.FILL, true, GridData.CENTER, false);

		createTableView(composite);

		handleFilterModify();

		return composite;
	}

	private void createTableView(Composite composite) {
		LayoutUtils.addWrapper(composite);
		classes = new PHPElementSelector(composite, SWT.BORDER | SWT.FULL_SELECTION);
		LayoutUtils.setGridData(classes, GridData.FILL, true, GridData.FILL, true);
		LayoutUtils.addWrapper(composite);

	    classes.addKeyListener(new KeyListener() {
			public void keyPressed(KeyEvent e) {
				handleListKeys(e);
			}
			public void keyReleased(KeyEvent e) {
			}
		});
	    classes.addMouseListener(new MouseListener() {
			public void mouseDoubleClick(MouseEvent e) {
				okPressed();
			}
			public void mouseDown(MouseEvent e) {
			}
			public void mouseUp(MouseEvent e) {
			}
		});
	}

	protected void okPressed() {
		selectedClass = classes.getItem(classes.getSelectionIndex());
		super.okPressed();
	}

	private void handleFilterModify() {
		classes.setRedraw(false);
		classes.removeAll();

		if (filter.getText().length() == 0) {
			classes.setRedraw(true);
			return;
		}

		if (phpClasses == null) {
			if (forClasses) {
				phpClasses = PHPElementContentProvider.getClasses();
			} else {
				phpClasses = PHPElementContentProvider.getInterfaces();
			}
		}
		for (int i = 0; i < phpClasses.length; i++) {
			PHPClassData phpClass = phpClasses[i];
			if (null != project) {
				try {
					if (project != ReflectionUtils.getProjectFor(phpClass)) {
						continue;
					}
				} catch (NullPointerException e) {
					continue;
				}
			}

			//TODO Process * and ? in filter text
			if (phpClass.getName().toLowerCase().indexOf(filter.getText().toLowerCase()) >= 0) {
				classes.addRow(phpClass);
			}
		}
		classes.setRedraw(true);
	}

	private void handleFilterKeys(KeyEvent e) {
		if (classes.getItemCount() == 0) {
			return;
		}
		if (SWT.ARROW_DOWN == e.keyCode || SWT.CR == e.keyCode || SWT.KEYPAD_CR == e.keyCode) {
			classes.setFocus();
			classes.select(0);
		}
	}

	private void handleListKeys(KeyEvent e) {
		if ((e.keyCode & SWT.KEYCODE_BIT) != 0) {
			return;
		}
		if ((e.keyCode > 'a' && e.keyCode < 'z') || (e.keyCode > 'A' && e.keyCode < 'Z')) {
			filter.setFocus();
			filter.setText(filter.getText() + e.character);
			filter.setSelection(filter.getText().length());
		} else if (e.keyCode == SWT.BS) {
			filter.setFocus();
			String text = filter.getText();
			if (text.length() == 0) {
				return;
			}
			filter.setText(text.substring(0, text.length() - 1));
			filter.setSelection(text.length() - 1);
		}
	}

}